package com.candoit.webapps.pricing.util;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;

import com.candoit.webapps.pricing.bean.PricingContext;
import com.candoit.webapps.pricing.model.ArmadoManoDeObra;
import com.candoit.webapps.pricing.model.Articulo;
import com.candoit.webapps.pricing.model.Categoria;
import com.candoit.webapps.pricing.model.CategoriaCuenta;
import com.candoit.webapps.pricing.model.CentroCostos;
import com.candoit.webapps.pricing.model.CentroCostosCriterio;
import com.candoit.webapps.pricing.model.ConsumoPapelMes;
import com.candoit.webapps.pricing.model.CriterioDistribucion;
import com.candoit.webapps.pricing.model.Cuenta;
import com.candoit.webapps.pricing.model.CuentaMes;
import com.candoit.webapps.pricing.model.Descuento;
import com.candoit.webapps.pricing.model.Formato;
import com.candoit.webapps.pricing.model.ImportFile;
import com.candoit.webapps.pricing.model.Linea;
import com.candoit.webapps.pricing.model.Maquina;
import com.candoit.webapps.pricing.model.MaquinaArticulo;
import com.candoit.webapps.pricing.model.MateriaPrima;
import com.candoit.webapps.pricing.model.MateriaPrimaArticulo;
import com.candoit.webapps.pricing.model.MateriaPrimaArticuloFK;
import com.candoit.webapps.pricing.model.Medida;
import com.candoit.webapps.pricing.model.Modelo;
import com.candoit.webapps.pricing.model.Moneda;
import com.candoit.webapps.pricing.model.OrdenTrabajo;
import com.candoit.webapps.pricing.model.OrdenTrabajoMes;
import com.candoit.webapps.pricing.model.Perfil;
import com.candoit.webapps.pricing.model.Rol;
import com.candoit.webapps.pricing.model.TipoLinea;
import com.candoit.webapps.pricing.model.TipoMateriaPrima;
import com.candoit.webapps.pricing.model.User;
import com.candoit.webapps.pricing.model.opcional.Manija;
import com.candoit.webapps.pricing.model.opcional.Opcional;

public class QueryUtil {
	
	private static QueryUtil instance = null;
	
	private EntityManager em = PricingContext.getInstance().getEntityManager();
	
	public static QueryUtil getInstance(){
		if (instance == null ){
			instance = new QueryUtil();
		}
		
		return instance;
	}
	
	@SuppressWarnings("unchecked")
	public List<Maquina> getMaquinas(){
		return (List<Maquina>) em.createQuery("select m from Maquina m ").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<CentroCostos> getCentroCostos(){
		return (List<CentroCostos>) em.createQuery("select c from CentroCostos c ").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<User> getUsers(){
		return (List<User>) em.createQuery("select u from User u ").getResultList();
	}
	
	public User getUserByUserName(String userName){
		try{
			User user = (User)em.createQuery("select u from User u where u.userName = :userName").setParameter("userName", userName).getSingleResult();
			return user;
		}catch(NoResultException e){
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Formato> getFormatos(){
		return (List<Formato>) em.createQuery("select f from Formato f ").getResultList();
	}
	
	public Formato getFormatoByMedidaAndLinea(Medida medida, Linea linea){
		try{
			return (Formato)em.createQuery("select f from Formato f where f.medida = :medida and f.linea = :linea ")
					.setParameter("medida", medida).setParameter("linea", linea).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Formato> getFormatosByIdLinea(Integer idLinea){
		return (List<Formato>) em.createQuery("select f from Formato f where  f.linea.id = :linea").setParameter("linea", idLinea).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Linea> getLineas(){
		return (List<Linea>) em.createQuery("select l from Linea l ").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Linea> getLineasIndustriales(){
		return (List<Linea>) em.createQuery("select l from Linea l where l.tipoLinea.id = :tipo")
								.setParameter("tipo", TipoLinea.INDUSTRIAL)
								.getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Linea> getLineasArtesanales(){
		return (List<Linea>) em.createQuery("select l from Linea l where l.tipoLinea.id = :tipo")
								.setParameter("tipo", TipoLinea.ARTESANAL)
								.getResultList();
	}
	
	public Linea getLineaByName(String name){
		try{
			return (Linea)em.createQuery("select l from Linea l where upper(l.nombre) = upper(:nombre)").setParameter("nombre", name).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	public Maquina getMaquinaByName(String name){
		try{
			return (Maquina)em.createQuery("select m from Maquina m where m.nombre = :nombre").setParameter("nombre", name).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	public TipoLinea getTipoLineaById(Integer id){
		try{
			return (TipoLinea)em.createQuery("select t from TipoLinea t where t.id = :id").setParameter("id", id).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	public TipoLinea getTipoLineaByDescripcion(String descripcion){
		try{
			return (TipoLinea)em.createQuery("select t from TipoLinea t where t.descripcion = :descripcion").setParameter("descripcion", descripcion).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<MateriaPrima> getMateriasPrimas(){
		return (List<MateriaPrima>) em.createQuery("select mp from MateriaPrima mp ").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Medida> getMedidas(){
		return (List<Medida>) em.createQuery("select m from Medida m ").getResultList();
	}
	
	public Medida getMedida(Integer ancho, Integer largo, Integer alto) throws NoResultException{
		return (Medida) em.createQuery("select m from Medida m where m.ancho = :ancho and m.largo = :largo and m.alto = :alto")
						.setParameter("ancho", ancho)
						.setParameter("largo", largo)
						.setParameter("alto", alto)
						
						.getSingleResult();
	}
	
	@SuppressWarnings("unchecked")
	public List<Modelo> getModelos(){
		return (List<Modelo>) em.createQuery("select m from Modelo m ").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Perfil> getPerfiles(){
		return (List<Perfil>) em.createQuery("select p from Perfil p ").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public int getCantMaquinasIndustrial(){
		try{
			List<Maquina> list = em.createQuery("select m from Maquina m where m.industrial = true").getResultList();
			return list.size();
		}catch(NoResultException e){
			return 0;
		}
	}
	
	@SuppressWarnings("unchecked")
	public int getCantMaquinasArtesanal(){
		try{
			List<Maquina> list = em.createQuery("select m from Maquina m where m.industrial = false").getResultList();
			return list.size();
		}catch(NoResultException e){
			return 0;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<CriterioDistribucion> getCriterios(){
		return (List<CriterioDistribucion>) em.createQuery("select c from CriterioDistribucion c where c.id != :id").setParameter("id", CriterioDistribucion.DIRECTA_CODE).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<String> getMaquinasNombres(){
		return (List<String>) em.createQuery("select m.nombre from Maquina m ").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public Double getSalarioByCentroCosto(CentroCostos cc, boolean simulado){
		List<CuentaMes> cuentas = em.createQuery("select c from CuentaMes c where c.cuentaMesFK.cuenta.centro = :cc " +
					"and c.cuentaMesFK.cuenta.descripcion = :descripcion "
					)
			.setParameter("cc", cc)
			.setParameter("descripcion", "MANO DE OBRA")
			.getResultList();
		
		CuentaMes cm = null;
		if(cuentas != null && !cuentas.isEmpty()){
			cm = cuentas.get(0);
			for(CuentaMes c : cuentas){
				if( MyTime.isAfter(c.getCuentaMesFK().getFecha(),cm.getCuentaMesFK().getFecha())) {
					cm = c;
				}
			}
			if (simulado){
				return cm.getCostoSimulado();
			}else{
				return cm.getCosto();
			}
			
		}else{
			return 0.0;
		}
		
	}
	
	@SuppressWarnings("unchecked")
	public List<Articulo> getArticulos(){
		return (List<Articulo>) em.createQuery("select a from Articulo a ").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Articulo> getArticulosByTipoLinea(TipoLinea tipoLinea){
		return (List<Articulo>) em.createQuery("select a from Articulo a where a.formato.linea.tipoLinea = :tipoLinea")
		.setParameter("tipoLinea", tipoLinea)
		.getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Articulo> getArticulosByLineas(List<Linea> lineas){
		return (List<Articulo>) em.createQuery("select a from Articulo a where a.formato.linea in (:lineas)").setParameter("lineas", lineas).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Articulo> getArticulosByFormato(Formato formato){
		return (List<Articulo>) em.createQuery("select a from Articulo a where a.formato = :formato ").setParameter("formato", formato).getResultList();
	}
	
	public Articulo getArticuloByCode(String codigo){
		try{
			return (Articulo)em.createQuery("select a from Articulo a where a.codigo = :codigo").setParameter("codigo", codigo).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	public MateriaPrimaArticulo getMateriaPrimaArticulo(Articulo articulo, TipoMateriaPrima materiaPrima){
		try{
			MateriaPrimaArticulo result = (MateriaPrimaArticulo) em.createQuery("select mpa from MateriaPrimaArticulo mpa where mpa.mpArticuloFK.articulo = :articulo and mpa.mpArticuloFK.materiaPrima = :materiaPrima")
																				.setParameter("articulo", articulo).setParameter("materiaPrima", materiaPrima).getSingleResult();
			return result;
		}catch (NoResultException e){
			return null;
		}
	}
	
	public MaquinaArticulo getMaquinaArticulo(Maquina maquina, Articulo articulo){
		try{
			MaquinaArticulo result = (MaquinaArticulo) em.createQuery("select ma from MaquinaArticulo ma where ma.maquinaArticuloFk.articulo = :articulo and ma.maquinaArticuloFk.maquina = :maquina")
																				.setParameter("articulo", articulo).setParameter("maquina", maquina).getSingleResult();
			return result;
		}catch (NoResultException e){
			return null;
		}
		
	}
	
	public Categoria getCategoriaProductiva(){
		try{
			Categoria result = (Categoria) em.createQuery("select c from Categoria c where c.id = :id").setParameter("id", Categoria.PRODUCTION_CODE).getSingleResult();
			return result;
		}catch (NoResultException e){
			return null;
		}
	}
	
	public Maquina getMaquinaByCentroCostos(CentroCostos centro){
		try{
			Maquina maquina = (Maquina) em.createQuery("select m from Maquina m where m.centro = :centro").setParameter("centro", centro).getSingleResult();
			return maquina;
		}catch(NoResultException e){
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Cuenta> getCuentas(){
		List<Cuenta> list = (List<Cuenta>) em.createQuery("select c from Cuenta c").getResultList();
		return list;
	}
	
	@SuppressWarnings("unchecked")
	public List<Cuenta> getCuentasByCentro(CentroCostos centro){
		List<Cuenta> list = (List<Cuenta>) em.createQuery("select c from Cuenta c where c.centro = (:centro)").setParameter("centro", centro).getResultList();
		return list;
	}
	
	public CentroCostos getCentroById(Integer id){
		try{
			return (CentroCostos) em.createQuery("select c from CentroCostos c where c.id =:id").setParameter("id", id).getSingleResult();
		}catch(Exception e){
			return null;
		}
	}
	
	public CentroCostosCriterio getCentroCostosCriterioObject(CentroCostos centro, CriterioDistribucion criterio){
		try{
			return (CentroCostosCriterio) em.createQuery("select c from CentroCostosCriterio c where c.fk.centro =:centro and c.fk.criterio = :criterio")
										  .setParameter("centro", centro).setParameter("criterio", criterio).getSingleResult();
		}catch(Exception e){
			return null;
		}
	}
	
	public CriterioDistribucion getCriterioDistribucionById(Integer id){
		try{
			return (CriterioDistribucion) em.createQuery("select c from CriterioDistribucion c where c.id =:id ")
										  .setParameter("id", id).getSingleResult();
		}catch(Exception e){
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public CuentaMes getUltimaCuenta(Cuenta cuenta){
		List<CuentaMes> cuentas = (List<CuentaMes>)em.createQuery("select c from CuentaMes c where c.cuentaMesFK.cuenta =:cuenta")
		  .setParameter("cuenta", cuenta).getResultList();
		CuentaMes cm = null;
		if(cuentas != null && !cuentas.isEmpty()){
			cm = cuentas.get(0);
			for(CuentaMes c : cuentas){
				if( MyTime.isAfter(c.getCuentaMesFK().getFecha(),cm.getCuentaMesFK().getFecha())) {
					cm = c;
				}
			}
			
		}
		return cm;
	}
	
//	public CuentaMes getCuentaMes(Cuenta cuenta, Integer mes){
//		try{
//			return (CuentaMes) em.createQuery("select c from CuentaMes c where c.cuentaMesFK.cuenta =:cuenta and c.cuentaMesFK.mes = :mes")
//										  .setParameter("cuenta", cuenta).setParameter("mes", mes).getSingleResult();
//		}catch(Exception e){
//			return null;
//		}
//	}
	
	@SuppressWarnings("unchecked")
	public List<CuentaMes> getCuentaMesByCuenta(Cuenta cuenta){
		return (List<CuentaMes>) em.createQuery("select c from CuentaMes c where c.cuentaMesFK.cuenta =:cuenta ")
										  .setParameter("cuenta", cuenta).getResultList();
	}
	
	public Double getCostoMesCentroCostos(CentroCostos  centro){
		List<Cuenta> cuentas = this.getCuentas();
		List<CentroCostos> centros = this.getCentroCostos();
		Double costo = 0.00d;
		Iterator<Cuenta> it = cuentas.iterator();
		while (it.hasNext()){
			   Cuenta cuenta = (Cuenta) it.next();
			   CuentaMes cuentaMes = this.getUltimaCuenta(cuenta);
			   if (cuenta.getCriterio() != null && cuentaMes!= null){
				   if (cuenta.getCriterio().getId() == CriterioDistribucion.DIRECTA_CODE){
					   if (cuentaMes != null){
						   costo += cuentaMes.getCosto() / centros.size();
					   }
				   }else{
					   CentroCostosCriterio centroCriterio = this.getCentroCostosCriterioObject(centro, cuenta.getCriterio());
					   	if (centroCriterio != null){	
					   		Double totalAsignado = QueryUtil.getInstance().getTotalAsignadoCriterio(cuenta.getCriterio());
					   		Double prorrateo = centroCriterio.getCantidad() / totalAsignado;
					   		if (cuentaMes != null){	
					   			costo += cuentaMes.getCosto() * prorrateo;
					   		}
					   	}	
				   }
			   }	   
		}
		return costo;
	}
	
	@SuppressWarnings("unchecked")
	public List<CentroCostos> getCentroCostosByCategoria(Integer categoria){
		List<CentroCostos> list = (List<CentroCostos>) em.createQuery("select cc from CentroCostos cc where cc.categoria.id = :categoria ").setParameter("categoria", categoria).getResultList();
		return list;
	}
	@SuppressWarnings("unchecked")
	public List<Integer> getCentroCostosIdByCategoria(Integer categoria){
		List<Integer> list = (List<Integer>) em.createQuery("select cc.id from CentroCostos cc where cc.categoria.id = :categoria ").setParameter("categoria", categoria).getResultList();
		return list;
	}
	
	public Categoria getCategoriaServicios(){
		try{
			Categoria result = (Categoria) em.createQuery("select c from Categoria c where c.id = :id").setParameter("id", Categoria.SERVICES_CODE).getSingleResult();
			return result;
		}catch (NoResultException e){
			return null;
		}
	}
	
	public Categoria getCategoriaSinAsignar(){
		try{
			Categoria result = (Categoria) em.createQuery("select c from Categoria c where c.id = :id").setParameter("id", Categoria.SIN_ASIGNAR_CODE).getSingleResult();
			return result;
		}catch (NoResultException e){
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<MateriaPrimaArticulo> getMateriaPrimaArticulos(Articulo articulo){
		List<MateriaPrimaArticulo> list = getMateriaPrimaArticulosSinMO(articulo);
		list.addAll(getMateriaPrimaArticulosConMO(articulo));
		return list;
	}
	
	
	
	@SuppressWarnings("unchecked")
	public List<MateriaPrimaArticulo> getMateriaPrimaArticulosSinMO(Articulo articulo){
		return (List<MateriaPrimaArticulo>) em.createQuery("select m from MateriaPrimaArticulo m where m.mpArticuloFK.articulo = :articulo and m.mpArticuloFK.materiaPrima.descripcion not like 'MO%'")
											.setParameter("articulo", articulo).getResultList();
		
	}
	
	@SuppressWarnings("unchecked")
	public List<MateriaPrimaArticulo> getMateriaPrimaArticulosConMO(Articulo articulo){
		return (List<MateriaPrimaArticulo>) em.createQuery("select m from MateriaPrimaArticulo m where m.mpArticuloFK.articulo = :articulo and m.mpArticuloFK.materiaPrima.descripcion like 'MO%'")
											.setParameter("articulo", articulo).getResultList();
		
	}
	
	@SuppressWarnings("unchecked")
	public List<Articulo> getMateriaPrimaArticulos(TipoMateriaPrima tmp){
		return (List<Articulo>) em.createQuery("select m from MateriaPrimaArticulo m where m.mpArticuloFK.materiaPrima = :materiaPrima")
											.setParameter("materiaPrima", tmp).getResultList();
		
	}
	
	@SuppressWarnings("unchecked")
	public List<TipoMateriaPrima> getTipoMateriaPrima(){
		return (List<TipoMateriaPrima>) em.createQuery("select t from TipoMateriaPrima t ").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<TipoMateriaPrima> getTipoMateriaPrimabyTipo(TipoLinea tipo){
		String setmp = "(1,2,3,4,5,6,7,8,9,10)";
		if(tipo.getId() == TipoLinea.INDUSTRIAL){
			setmp = "(1,2,3,4,5,6,7,8,9,10)";
		}else if(tipo.getId() == TipoLinea.ARTESANAL){
			setmp = "(8,11,12,13,14,15,16,17,18)";
		}else if(tipo.getId() == TipoLinea.SEMIARTESANAL){
			setmp = "(1,4,5,6,7,8,9,10,19)";
		}
		return (List<TipoMateriaPrima>) em.createQuery("select t from TipoMateriaPrima t where t.id in "+setmp).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<TipoMateriaPrima> getTipoMateriaPrimaExceptsMO(){
		return (List<TipoMateriaPrima>) em.createQuery("select t from TipoMateriaPrima t where t.id not in (8,9,10,14,15) ").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<TipoMateriaPrima> getTipoMateriaPrimaExceptsMOByTipo(TipoLinea tipo){
		return (List<TipoMateriaPrima>) em.createQuery("select t from TipoMateriaPrima t where t.id not in (8,9,10,14,15,16) and t.tipo = :tipo")
						.setParameter("tipo", tipo)
						.getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<CentroCostosCriterio> getCentroCostoCriterio(CentroCostos centro ){
		return (List<CentroCostosCriterio>) em.createQuery("select c from CentroCostosCriterio c where c.fk.centro = :centro ")
											.setParameter("centro", centro).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<OrdenTrabajo> getOrdenesTrabajo(){
		return (List<OrdenTrabajo>) em.createQuery("select ot from OrdenTrabajo ot").getResultList(); 
	}
	
	public OrdenTrabajoMes getOrdenTrabajoByOTMes(Integer ot, Integer mesActual){
		try{
			OrdenTrabajoMes result = (OrdenTrabajoMes) em.createQuery("select ot from OrdenTrabajoMes ot where ot.fk.orden.id = :id and ot.fk.mes = :mes")
					                 .setParameter("id", ot).setParameter("mes", mesActual).getSingleResult();
			return result;
		}catch (NoResultException e){
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<ConsumoPapelMes> getConsumoPapelMes(){
		return (List<ConsumoPapelMes>) em.createQuery("select c from ConsumoPapelMes c").getResultList();
	}
	
	public ConsumoPapelMes getConsumoPapelMes(Integer id){
		try{
			ConsumoPapelMes consumo = (ConsumoPapelMes) em.createQuery("select c from ConsumoPapelMes c where c.orden.id = :id")
									 .setParameter("id", id).getSingleResult();
			return consumo;
		}catch (NoResultException e){
			return null;
		}			
	}
	
	public ConsumoPapelMes getConsumoPapelByOTMes(OrdenTrabajo ot){
		try{
			ConsumoPapelMes result = (ConsumoPapelMes) em.createQuery("select c from ConsumoPapelMes c where c.fk.orden = :orden")
					                 .setParameter("orden", ot).getSingleResult();
			return result;
		}catch (NoResultException e){
			return null;
		}
	}
	
//	@SuppressWarnings("unchecked")
//	public List<CuentaMes> getCuentasByMes(Integer mesActual){
//		return (List<CuentaMes>) em.createQuery("select c from CuentaMes c where c.cuentaMesFK.mes = :mes").setParameter("mes", mesActual).getResultList();
//	}
	
	@SuppressWarnings("unchecked")
	public List<CuentaMes> getCuentasMesByCuenta(Cuenta cuenta){
		return (List<CuentaMes>) em.createQuery("select c from CuentaMes c where c.cuentaMesFK.cuenta = :cuenta").setParameter("cuenta", cuenta).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<MateriaPrima> getMateriaPrimaFilter(){
		List<Integer> ids = new ArrayList<Integer>();
		ids.add(58);ids.add(78);ids.add(79);ids.add(81);ids.add(82);ids.add(83);
		return (List<MateriaPrima>) em.createQuery("select m from MateriaPrima m where m.id in (:ids) ").setParameter("ids", ids).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<MateriaPrima> getMateriaPrimaByPapel(){
		return (List<MateriaPrima>) em.createQuery("select m from MateriaPrima m where m.tipoMateriaPrima.id = :tipo ").setParameter("tipo", TipoMateriaPrima.PAPEL).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<MateriaPrima> getMateriaPrimaByCartulina(){
		return (List<MateriaPrima>) em.createQuery("select m from MateriaPrima m where m.tipoMateriaPrima.id = :tipo ").setParameter("tipo", TipoMateriaPrima.CARTULINA).getResultList();
	}
	
	//TODO: Sacar
	@SuppressWarnings("unchecked")
	public List<MateriaPrima> getMateriaPrimaByPapelActivos(){
		return (List<MateriaPrima>) em.createQuery("select m from MateriaPrima m where m.tipoMateriaPrima.id = :tipo and m.activo = true").setParameter("tipo", TipoMateriaPrima.PAPEL).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<MateriaPrima> getMateriaPrimaByPapelActivosAndTipoMateriaPrima(Integer tipoMateriaPrima){
		return (List<MateriaPrima>) em.createQuery("select m from MateriaPrima m where m.tipoMateriaPrima.id = :tipo and m.activo = true")
		.setParameter("tipo", tipoMateriaPrima)
		.getResultList();
	}
	
	public Double getTotalAsignadoCriterio(CriterioDistribucion criterio){
		return (Double) em.createQuery("select SUM(c.cantidad) from CentroCostosCriterio c where c.fk.criterio = :criterio")
									  .setParameter("criterio", criterio).getSingleResult();	
	}
	
	public Double getTotalAsignadoCriterioExceptsCC(Integer idCriterio, Integer idCentro){
		return (Double) em.createQuery("select SUM(c.cantidad) from CentroCostosCriterio c where c.fk.criterio.id = :idCriterio and c.fk.centro.id != :idCentro")
									  .setParameter("idCriterio", idCriterio).setParameter("idCentro", idCentro).getSingleResult();	
	}
	
	public Medida getMedidaFilter(Integer ancho, Integer largo, Integer alto){
		try{
			Medida result = (Medida) em.createQuery("select m from Medida m where m.ancho = :ancho and m.largo = :largo and m.alto = :alto")
					                 .setParameter("ancho", ancho).setParameter("largo", largo).setParameter("alto", alto).getSingleResult();
			return result;
		}catch (NoResultException e){
			return null;
		}
	}
	
	public Double getCostoMesManoDeObra(CentroCostos  centro){
		List<Cuenta> cuentas = this.getCuentaManosDeObra();
		Double costo = 0.00d;
		Iterator<Cuenta> it = cuentas.iterator();
		while (it.hasNext()){
			   Cuenta cuenta = (Cuenta) it.next();
			   if (cuenta.getCentro().getId() == centro.getId()){
				   CuentaMes cuentaMes = this.getUltimaCuenta(cuenta);
				   if (cuentaMes != null){
					   costo = cuentaMes.getCosto();
				   }
			  }
		}
		return costo;
	}
	
	@SuppressWarnings("unchecked")
	public List<Cuenta> getCuentaManosDeObra(){
		return (List<Cuenta>) em.createQuery("select c from Cuenta c where c.descripcion =:descripcion ")
				.setParameter("descripcion", "MANO DE OBRA").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<CentroCostos> getCentrosUtecoNewLong(){
		List<Integer> ids = new ArrayList<Integer>();
		ids.add(16);ids.add(17);
		return (List<CentroCostos>) em.createQuery("select cc from CentroCostos cc where cc.id in (:ids)")
				.setParameter("ids", ids).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<TipoMateriaPrima> getTipoMateriaPrimaManoDeObra(){
		List<Integer> ids = new ArrayList<Integer>();
		ids.add(TipoMateriaPrima.MO_CONFECCION);
//		ids.add(TipoMateriaPrima.MO_EMPAQUE);
		ids.add(TipoMateriaPrima.MO_IMPRESION);
		return (List<TipoMateriaPrima>) em.createQuery("select t from TipoMateriaPrima t where t.id in (:ids)")
				.setParameter("ids", ids).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Articulo> getArticulosByLinea(Linea linea){
		return (List<Articulo>) em.createQuery("select a from Articulo a where a.formato.linea = :linea")
				.setParameter("linea", linea).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Articulo> getArticulosByLineaByArticulo(Linea linea, Articulo articulo){
		return (List<Articulo>) em.createQuery("select a from Articulo a where a.formato.linea = :linea and a.id = :id ")
				.setParameter("linea", linea).setParameter("id", articulo.getId()).getResultList();
	}
	
	public MateriaPrima getMateriaByDescription(String descripcion){
		try{
			return (MateriaPrima) em.createQuery("select c from MateriaPrima c where c.nombre = :descripcion")
							.setParameter("descripcion", descripcion).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	public Cuenta getCuentaByDescription(String descripcion, CentroCostos centro){
		try{
			return (Cuenta) em.createQuery("select c from Cuenta c where c.descripcion = :descripcion and c.centro = :centro")
							.setParameter("descripcion", descripcion).setParameter("centro", centro).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	public Cuenta getCuentaByCategoria(String descripcion, CategoriaCuenta categoria){
		try{
			return (Cuenta) em.createQuery("select c from Cuenta c where c.descripcion = :descripcion and c.categoria = :categoria")
							.setParameter("descripcion", descripcion).setParameter("categoria", categoria).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Cuenta> getAllCuentasByCategoria(CategoriaCuenta categoria){
		try {
			return (List<Cuenta>)em.createQuery("select c from Cuenta c where c.categoria = :categoria")
								.setParameter("categoria", categoria).getResultList();
		} catch (Exception e) {
			return null;
		}
	}
	
	public List<CuentaMes> getCuentasByMesExceptsMO(){
		List<Cuenta> cuentas = this.getCuentas();
		Iterator<Cuenta> it = cuentas.iterator();
		while(it.hasNext()){
			Cuenta c = it.next();
			if(c.getDescripcion().equals("MANO DE OBRA")){
				it.remove();
			}
		}
		
		List<CuentaMes> cms = new ArrayList<CuentaMes>();
		for(Cuenta c : cuentas){
			CuentaMes cm = getUltimaCuenta(c);
			if(cm!=null){
				cms.add(cm);
			}
		}
		
		return cms;
//		return (List<CuentaMes>) em.createQuery("select c from CuentaMes c where c.cuentaMesFK.mes = :mes and c.cuentaMesFK.cuenta.descripcion != :descripcion ")
//				.setParameter("mes", mesActual).setParameter("descripcion", "MANO DE OBRA").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<CategoriaCuenta> getAllCategoriaCuentas(){
		return (List<CategoriaCuenta>) em.createQuery("select c from CategoriaCuenta c").getResultList();
	}
	
	public List<CuentaMes> getCuentasByMesManoDeObra(){
		List<Cuenta> cuentas = this.getCuentas();
		Iterator<Cuenta> it = cuentas.iterator();
		while(it.hasNext()){
			Cuenta c = it.next();
			if(!c.getDescripcion().equals("MANO DE OBRA")){
				it.remove();
			}
		}
		
		List<CuentaMes> cms = new ArrayList<CuentaMes>();
		for(Cuenta c : cuentas){
			CuentaMes cm = getUltimaCuenta(c);
			if(cm!=null){
				cms.add(cm);
			}
		}
		
		return cms;
		//		return (List<CuentaMes>) em.createQuery("select c from CuentaMes c where c.cuentaMesFK.mes = :mes and c.cuentaMesFK.cuenta.descripcion = :descripcion ")
		//				.setParameter("mes", mesActual).setParameter("descripcion", "MANO DE OBRA").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<CentroCostos> getCentrosListOrderByCatgory(){
		return (List<CentroCostos>) em.createQuery("select c from CentroCostos c order by c.categoria.id ").getResultList();
	}
	
	public Double getCostoPromedioByTipoMateria(TipoMateriaPrima tipo){
		try{
		return (Double) em.createQuery("select AVG(c.costoUnitario) from MateriaPrima c where c.tipoMateriaPrima = :tipo")
									  .setParameter("tipo", tipo).getSingleResult();	
		}catch(NoResultException e){
			return 0.00d;
		}
	}
	
	/*No es valido para papel*/
	@SuppressWarnings("unchecked")
	public List<MateriaPrima> getMateriaPrimaByTipoMateria(TipoMateriaPrima tipo){
		List<MateriaPrima> list = null;
		try{
		list =  (List<MateriaPrima>) em.createQuery("select c from MateriaPrima c where c.tipoMateriaPrima = :tipo")
									  .setParameter("tipo", tipo).getResultList();	
		}catch(NoResultException e){
			list = null;
		}
		return list;
	}
	
	public TipoMateriaPrima getTipoMateriaPrimaById(Integer id){
		try{
			return (TipoMateriaPrima) em.createQuery("select c from TipoMateriaPrima c where c.id= :id")
							.setParameter("id", id).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	public CentroCostos getCentroByDesc(String desc){
		try{
			return (CentroCostos) em.createQuery("select c from CentroCostos c where c.nombre= :desc")
							.setParameter("desc", desc).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	public CategoriaCuenta getCategoriaByDesc(String desc){
		try{
			return (CategoriaCuenta) em.createQuery("select c from CategoriaCuenta c where c.descripcion= :desc")
							.setParameter("desc", desc).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	public Double getTotalKgConsumoPapel(Integer mes){
	try{
		return (Double) em.createQuery("select SUM(c.kilos) from ConsumoPapelMes c where c.fk.mes = :mes")
									  .setParameter("mes", mes).getSingleResult();	
		}catch(NoResultException e){
			return 0.00d;
		}
	}
	
	public Long getTotalOrdenTrabajo(Integer mes){
		try{
			return (Long) em.createQuery("select SUM(c.cantidad) from OrdenTrabajoMes c where c.fk.mes = :mes")
										  .setParameter("mes", mes).getSingleResult();	
			}catch(NoResultException e){
				return 0l;
			}
		}
	
	public TipoMateriaPrima getTipoMateriaPrimaByDesc(String desc){
		try{
			return (TipoMateriaPrima) em.createQuery("select c from TipoMateriaPrima c where c.descripcion= :desc")
							.setParameter("desc", desc).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	public MateriaPrima getMateriaByDescriptionAndTipo(String descripcion, TipoMateriaPrima tipo){
		try{
			return (MateriaPrima) em.createQuery("select c from MateriaPrima c where c.nombre = :descripcion and c.tipoMateriaPrima = :tipo ")
							.setParameter("descripcion", descripcion).setParameter("tipo", tipo).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<CentroCostosCriterio> getCentroCostoCriterioByCriterio(CriterioDistribucion criterio ){
		return (List<CentroCostosCriterio>) em.createQuery("select c from CentroCostosCriterio c where c.fk.criterio = :criterio")
											.setParameter("criterio", criterio).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Cuenta> getCuentaByCriterio(CriterioDistribucion criterio ){
		return (List<Cuenta>) em.createQuery("select c from Cuenta c where c.criterio = :criterio")
											.setParameter("criterio", criterio).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<ImportFile> getImportsFiles(){
		return (List<ImportFile>) em.createQuery("select i from ImportFile i ").getResultList();
	}
	
	public ImportFile getImportFileById(Integer id){
		try{
			return (ImportFile) em.createQuery("select i from ImportFile i where i.id= :id ")
							.setParameter("id", id).getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Moneda> getMonedas(){
		return (List<Moneda>) em.createQuery("select m from Moneda m ").getResultList();
	}
	
	public Moneda getCotizacionMoneda(){
		try{
			return (Moneda) em.createQuery("select m from Moneda m where m.activo = true ").getSingleResult();
		}catch(Exception e){
			return (Moneda) em.createQuery("select m from Moneda m where m.id = :id ").setParameter("id", Moneda.DOLLAR_CODE).getSingleResult();
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Rol> getRoles(){
		return (List<Rol>) em.createQuery("select r from Rol r ").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Descuento> getDescuentosByLinea(Linea linea){
		return (List<Descuento>) em.createQuery("select d from Descuento d where d.fk.linea = :linea").setParameter("linea", linea).getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<ArmadoManoDeObra> getArmados(){
		return (List<ArmadoManoDeObra>) em.createQuery("select a from ArmadoManoDeObra a").getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Opcional> getOpcionales(Class<? extends Opcional> clase, Double margenUtilidad){
		List<Opcional> opcionales = em.createQuery("select m from "+clase.getName()+" m").getResultList();
		for(Opcional t : opcionales){
			t.setMargenUtilidad(margenUtilidad);
		}
		return opcionales;
	}

	@SuppressWarnings("unchecked")
	public <T extends Opcional>List<? extends Opcional> getOpcionales2(Class<? extends Opcional> clase, Double margenUtilidad){
		List<T> opcionales = em.createQuery("select m from "+clase.getName()+" m").getResultList();
		for(T t : opcionales){
			t.setMargenUtilidad(margenUtilidad);
		}
		return opcionales;
	}
	
	public ArmadoManoDeObra getArmadoByDescripcion(String descripcion){
		try{
			return (ArmadoManoDeObra) em.createQuery("select a from ArmadoManoDeObra a where a.descripcion = :descripcion ")
			.setParameter("descripcion", descripcion)
			.getSingleResult();
		}catch(Exception e){
			return null;
		}
	}
}
